約 4,581,524 件
https://w.atwiki.jp/cod5zombies/pages/19.html
ここでは今現在Zombie Realismに残っている重傷な不具合・バグの報告と解決方法を載せています。 ◆新v2.2の不具合 既存のセーブデータを「zombie_realism_v2.2」で実行しようとすると、エラーがでて、既存のセーブデータが適応されない。→その救済策として、プレイ時間2時間まで経験値を通常の10倍取得することが出来る。 ゾンビが正しく沸かない。沸きゾーンで勝手に死ぬ→nazi_zombie_sbやnazi_zombie_berlinbank、ZTCマップなどで確認。 サポート自身が自分の置いた弾薬箱から弾薬を補給できない。→マップによって異なる。Der Riese系のマップだと正しく動作しやすい。 新規プロフィールでホストをやると、ロビーにいる全員が経験値ボーナスをもらえるマップがある。 カスタムクラスで、クラスアビリティがうまく反映されない。→解決法なし。 ◆v2.2以降不解決組み マルチプレイで、2回リロードのモーションが入り、リロードにタイムロスが発生する→Sleight of Handのバグか? ◇v2.2以降解決組み マルチプレイで、ゾンビカウンターが機能しない。→ホストのみ確認可能。 マルチプレイで、Perkマシンの修復や電源を入れられない時がある→Patch1で修正済み? もしくはエンジニアが一回死ぬ必要があります。 マルチプレイで、チャットやVCができない→「onlinegame 1」とコンソールに入力。 マルチプレイで、弾薬箱から弾が拾えない→新v2.2で修正 マルチプレイで、サポートでもないのに弾薬箱を持ってスポーンすることがある→新v2.2で修正されたかも。 マルチプレイで、壁武器・ランダムボックスから武器や弾薬が買えない、拾えない→新v2.2で修正されたかも。 他にも不具合があれば報告お願いします。 旧2.2データを移行できないのは仕様かな。 -- Bakehead (2011-08-31 15 17 47) 旧2.2はv2と同じフォルダのデータなので、レジストリ操作しない限り無理そうです。 -- MQ (2011-09-05 22 27 13) エンジニアのアップグレートポイントは死んでも解決しないときがあり ポイントを使うことによって解決する事もある -- Qoo (2011-09-06 12 03 33) 名前 コメント
https://w.atwiki.jp/switchsoft/pages/493.html
ブレイブダンジョン+魔神少女COMBAT DRPG ハクスラ カードオリジナル カードゲーム トランプ-ポーカー(ミニゲーム) 864円(税込)876MB→881MB オープンワールドRPG+オールスターカードバトルの2本セット! 【ブレイブダンジョン】 フリーパーティー・オープンワールドRPG! 攻略も成長も自由に決めよう! 5人のキャラクターから選んだ3人パーティーでダンジョンを探索するRPGです。 ダンジョン探索 宝が眠る「ゴッズヒル」をクリアすることが目的ですが 全部で5つあるダンジョンを好きな順番で攻略していくことができます。 もちろん「ゴッズヒル」は序盤では難しいですが、 ほかのダンジョンを探索してキャラクターを成長させることで、 「ゴッズヒル」の探索をすることができるようになります。 キャラクター成長 キャラクターやパーティーを強くする方法がさまざまに用意されています。 経験値によるレベルアップ・素材合成で作成するアクセサリ・クラスチェンジ マジックアイテム・ステータス振り分け・ゴハンタイム など、プレイヤーの好みの方法を模索できるようになっています。 やりこみ要素 ゲームをクリアした後にはさらなる高難易度のダンジョンの登場や 条件をクリアすることでおまけ画像が見れる「プレイングレベル」 2周目からパワーアップできるアイテムが手に入る「シェガーショップ」 シェガーショップで使用するシェガーをあつめる「ポーカー」「テキヨケランナー」 ゲームコインを使ってドット絵を集めてデコれる「シェガチャ」など ゲームを1度クリアした後もいろいろと遊べるようなシステムが登場します。 【魔神少女COMBAT】 「コンバット」と呼ばれるオールスターカードバトルで熱くなろう! 1人用のクエストモードと2人用のバトルモードで最強のコンバットプレイヤーを決めよう! クエストモード ストーリーに沿ってコンバットアリーナのチャンピオンを目指す1人用のゲームモードです。 手に入れたカードから3枚をメインメンバーを選び、コンバットプレイヤーが集まる「バトルアリーナ」で 最強のコンバットプレイヤーを目指すモードです。 強いカードが必ず勝てるわけじゃない!? ただ能力が高いカードが必ず勝てるわけではありません。コンバットには各カードに装備できる「マジックアイテム」や 特定のカードの組み合わせによって「チームスキル」という特別な力が発動するなど、さまざまな戦略が存在します。 お気にいりのカードを特別に強くする カードを育てるにはバトルに参加するのはもちろんですが、特別に愛情を注いだりすることで、特別に強化することもできます! さらに成長を続けるとカードを進化させることができ、より強力なカードに変化します。 ぱっと見は弱いカードでも強力なカードになることもあるかも!? 配信日 2017年9月28日 メーカー INSIDE SYSTEM 対応ハード Nintendo Switch 対応コントローラー Nintendo Switch Proコントローラー プレイモード TVモード, テーブルモード, 携帯モード プレイ人数1~2人 ブレイブダンジョン:1人 魔神少女COMBAT:2人 対応言語 日本語, 英語 CERO B セクシャル セール履歴ブレイブダンジョン+魔神少女COMBAT ゴールデンウィークセール! 604円(30%off) 2018/4/26 00 00~2018/5/9 23 59 ブレイブダンジョンシリーズ 年末セール30%OFF! 604円(30%off) 2018/11/29 00 00~2018/12/12 23 59 3DS版はサクサク進めて自分は結構楽しめた ただ基本的にはレベル上げればどうとでもなるゲームだからシビアなゲームを求めてる人はイマイチかも 最後の方は通常攻撃を乱れ撃ちするアクセサリ集めてただ殴るだけになりがち -- 名無しさん (2018-07-12 23 00 37) ブレイブダンジョンはサクサク快適だなあ。 逆にカードゲーの方はイマイチテンポが悪い気がする。 …そもそもルール説明が無いんだが。 マジで序盤は運でクリアしていかないと駄目なんか? -- 名無しさん (2018-07-13 17 25 18) ブレダン 3DSでやってないなら買い COMBATはまぁまぁ面白いが戦略性皆無 キャラを愛でるものだなコレ -- 名無しさん (2018-07-14 07 03 55) 固定ダンジョン固定敵シンボル、戦闘はコマンド選択のRPG ストーリーはほぼ無くて、キャラをチマチマ強くしてボスを倒してくだけ これだけ聞くとつまらなそうなんだけど、全体的に丁寧に作り込まれててストレス要素も少ないので値段以上には楽しめる エンディングまで9時間くらいで、周回要素とやりこみ要素を全部やって25時間くらいだったかな 一緒についてる魔神少女COMBATはどうしようもないゴミなのでやらなくていい -- 名無しさん (2018-07-28 14 30 29) Q.ブレイブダンジョンで一番やったことはなんですか? A.ポーカー -- 名無しさん (2018-07-28 14 33 31) ブレイブダンジョンは1週クリアに10時間でぼちぼち楽しめた シナリオほぼ無いけど戦闘は単調ながらRPGらしい作り 敵のドットが結構作り込まれてる 作業感が強めのシンプルでお手軽な作り 後半はバランスが崩壊してくるのでレベルを上げすぎるとヌルゲー化する ヌルゲーを目指して頑張るのが好きな俺には楽しめた 一応周回要素あり 強くてニューゲームも弱くてニューゲームも可能 魔神少女combatはクソゲー カードバトルというには運が絡みすぎて戦略も何も無い単調なシステム カードが経験値でレベルアップするのも意味分からん 暇つぶしにもならないというか時間の無駄 -- 名無しさん (2018-07-29 19 03 50) 覚えることの多いRPGが面倒だから、ブレイブダンジョンくらいのシンプルなシステムが俺には丁度良かったな。 アクション本編よりも、こっちの外伝の続編が欲しいくらいw -- 名無しさん (2018-07-29 19 04 11) ブレイブダンジョン酷いわ プレイが単調で退屈すぎる脳死ゲーを最後まで頑張ってプレイしてクリアしたら 急にクリア後のやりこみ要素が出て来て続けちゃう悔しい 手のひらで転がされてる -- 名無しさん (2018-08-06 08 14 16) ブレイブダンジョンは 見た目チープな感じだけど結構な時間泥棒ゲーム 低価格ゲームを買おうとして迷ったら買ってみて欲しい カップリングのコンバットは微妙 抱き合わせ商法感 -- 名無しさん (2019-08-11 18 43 05) 低難易度+短時間でサクッとクリアできるゲームならブレイブダンジョンが良かったかな エンディング後のおまけダンジョンもダラダラとプレイできたし -- 名無しさん (2019-12-23 15 58 07) 結構前に本気でクソだと思って投げ出していたコンバットを気まぐれに再開してみたけどクリア前はともかくクリア後の裏面は意外に面白かったわ。 収入と支出のバランスがかなりマシになって割と遊びやすくなるし、互いに育成が進むことで戦況を大きく変えられるアイテムが使えるようになって最低限の戦略性が生まれる。 それでも選択肢は多くないし突き詰めるには運要素が強すぎるけどブレイブダンジョンのオマケとしては十分だと思う。 あと、各ダンジョンのボスや原作の少女達のカードがちゃんと強いのでそいつらが好きならさらに楽しめるの明確に素晴らしい点だ。 ただしカードゲームというよりは育成ゲームとかに近い面白さなのと、稼ぎ中は操作できないので片手にスマホがないと流石に辛くなりそうな点には注意が必要。 そして序盤は本当にクソを越えたクソなので一回投げ出した人が再開するならともかく、一切触ってない人が新しく始める場合に俺と同じように楽しめる保証は無い事も書いておく。 -- 名無しさん (2024-06-22 19 26 51) 名前 コメント
https://w.atwiki.jp/cod4mod/pages/21.html
The Battlechatter System is Singleplayer Only function. For Call of Duty 4 BCS only supports US Forces. British singleplayer levels did not have BCS. Battlechatter uses triggers. When an NPC is inside the trigger it tells the other NPC s there location. There are "Locations" and "Landmarks" Battlechatter システムはシングルプレイヤーです、ただ機能。 Call of Duty のために4つのBCSがただ合衆国軍を支援するだけです。 英国の singleplayer レベルがBCSを持っていませんでした。 Battlechatter はトリガーを使います。NPC がトリガーの中にあるとき、それは他に NPC がそこにロケーションであると言います。 「ロケーション」と「ランドマーク」があります Making a Location To make a location you first make a brush covering the area and then make it into a trigger_multiple. On the trigger you would enter in the type of location in the Key/Value. ロケーションを作るために、あなたは最初にブラシカバーリングをその区域にして、そして次にそれを trigger_multiple に加工します。 トリガーであなたはキー / 値でロケーションのタイプを入力するでしょう。 Example Key script_location Value thirdfloor Key targetname Value trigger_location Then on the nodes inside the BCS trigger you would put what best fits the area the node is located それからBCSトリガーの中にノードの上にあなたはノードがそうである最も良い適合度、区域、が位置を定めたものを置くでしょう Example Key script_location Value window Making a Landmark Place a trigger_radius and add the Key/Value that best fits the area. trigger_radius を置いて、そして最も良くその区域に適しているキー / 値を加えてください。 Example Key targetname Value trigger_landmark Key script_landmark Value boxes This is a list of locations and Landmarks that are available. これはロケーションのリストと利用可能なランドマークです。 Locations basement_generic basement_window firstfloor_doorway firstfloor_generic firstfloor_window roof_generic rooftop secondflr_balcony secondflr_doorway secondflr_generic secondflr_window thirdfloor_balcony thirdfloor_generic thirdfloor_window topfloor_balcony topfloor_generic topfloor_window tower Landmarks apc armoredvehicle barrels barricade bmp boxes bradley bulldozer bus car carblue carbrown cargocontainer cargreen carred carwhite carwrecked cinderblocks concretepipe couch crate crater desk dumpster extdoorway fence fountain fridge garage gate hatchback humvee intdoorway marketstand outhouse palmtrees pilelumber sandbags semi shed statue steps table tank tires trailer trashcans trees truck truckblue truckbrown truckdestroyed truckgreen truckpickup truckred truckwhite van vanblue vanbrown vandestroyed vangreen near_vanred near_vanwhite near_wall near_wallbroken near_wallcinderblock near_walllow near_wallstone near_washingmachine near_window (Original "http //www.infinityward.com/wiki/index.php?title=Battlechatter_System") 名前 すべて読む
https://w.atwiki.jp/clanfaf/pages/35.html
ここでは某隊員が撮影したプレイ動画を見ることができます。 タイトル別にページがリンクしているので、「見たいな」とか「興味あるな」etc... .....とか思ったあなた。ぜひご覧ください。 BLAZBLUE Halo Reach Call of Duty Modern Warfare 2 Battlefield Bad Company 2 Devil May Cry 4 Command Conquer 3 Tiberium Wars ACE COMBAT 6 解放への戦火 METAL GEAR SOLID 4 GUNS OF THE PATRIOT GRAN TURISMO 5 Prologue ページ管理者 Mr himazin
https://w.atwiki.jp/trinanoss/pages/15.html
クロスSS作品別インデックス A~M N~Z あ行 か行 さ行 た行 な行 は行 ま行 や行 ら行 わ行 A~M 作品タイトル クロス元 作者 ACE COMBAT ~THE UNSUNG Striker~ ACE COMBAT5 ~THE UNSUNG WAR~ F-16CCV氏 THE OPERATION LYRICAL ACE COMBAT04 T-2改氏 Call of Lyrical4 CALL OF DUTY4 MODERN WARFARE T-2改氏 Gears Of Lyrical Gears Of War 第22SAS連隊隊員氏 HALO THE LYRICAL HALO3 第22SAS連隊隊員氏 上へ N~Z 作品タイトル クロス元 作者 上へ あ行 作品タイトル クロス元 作者 上へ か行 作品タイトル クロス元 作者 上へ さ行 作品タイトル クロス元 作者 上へ た行 作品タイトル クロス元 作者 魔法少女リリカルなのはSAVERS デジモンセイバーズ やまさん氏 上へ な行 作品タイトル クロス元 作者 上へ は行 作品タイトル クロス元 作者 上へ ま行 作品タイトル クロス元 作者 上へ や行 作品タイトル クロス元 作者 上へ ら行 作品タイトル クロス元 作者 上へ わ行 作品タイトル クロス元 作者 上へ
https://w.atwiki.jp/ddrdp/pages/1556.html
Bombay Bomb(踊) 曲名 アーティスト フォルダ 難易度 BPM NOTES/FREEZE その他 Bombay Bomb Jena Rose 2013 踊10 145 327 / 0 STREAM VOLTAGE AIR FREEZE CHAOS 59 42 0 0 15 楽譜面(6) / 踊譜面(10) / 激譜面(12) / 鬼譜面(-) 属性 渡り、交互難 譜面 http //eba502.web.fc2.com/fumen/ddr/ddr2013/bombay_b_8t.html プレイ動画 https //youtu.be/FNJYYtyDrV8?t=2m20s (x2.0, NOTE, 2 20~) 解説 DPでは珍しい交互難譜面。スライドのポイントを見切れないと厳しい。曲が長くノーツも多いので集中力と応用力が問われる。 -- 名無しさん (2014-02-26 00 28 10) 2013以降から増え出した交差渡りが存分に含まれた譜面。4分経由での繋ぎが多いので、一見すると交互に踏めるように見えないのがクセモノ。8分3連主体なので、4分はスライドで対処しても已む無しだろう -- 名無しさん (2015-05-10 22 24 34) 名前 コメント コメント(私的なことや感想はこちら) ボ ン ベ イ ボ ム -- 名無しさん (2014-02-25 12 38 45) ボックスとか多用して全交互するの楽しい -- 名無しさん (2014-03-07 10 56 45) 名前 コメント
https://w.atwiki.jp/akasatanahama/pages/106.html
概要 MOD製作チュートリアル/TileEntityの追加で追加したTileEntityにGUI(Graphical User Interface)を実装する。 動作確認済バージョン:1.7.10-10.13.4.1558 ソースコード AluminiumMod.java package tutorial.aluminiummod; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.registry.GameRegistry; import net.minecraft.block.Block; @Mod(modid = AluminiumMod.MODID, name = AluminiumMod.MODNAME, version = AluminiumMod.VERSION) public class AluminiumMod { public static final String MODID = "AluminiumMod"; public static final String MODNAME = "Aluminium Mod"; public static final String VERSION = "1.0.0"; @Instance(MODID) public static AluminiumMod instance; public static Block chestAluminium; @EventHandler public void perInit(FMLPreInitializationEvent event) { chestAluminium = new BlockAluminiumChest() .setBlockName("chestAluminium") .setBlockTextureName("aluminiummod Aluminium_Chest"); GameRegistry.registerBlock(chestAluminium, "chestAluminium"); GameRegistry.registerTileEntity(TileEntityAluminiumChest.class, "TileEntityAluminiumChest"); NetworkRegistry.INSTANCE.registerGuiHandler(this.instance, new AluminiumModGuiHandler()); } } BlockAluminiumChest.java package tutorial.aluminiummod; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class BlockAluminiumChest extends Block implements ITileEntityProvider { private Random random = new Random(); public BlockAluminiumChest() { super(Material.rock); this.setCreativeTab(CreativeTabs.tabDecorations); this.setHardness(5.0F); this.setResistance(1.0F); this.setStepSound(soundTypeMetal); isBlockContainer = true; } @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityAluminiumChest(); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { // GUIを開く。 player.openGui(AluminiumMod.instance, 1, world, x, y, z); return true; } @Override public void breakBlock(World world, int x, int y, int z, Block block, int meta) { // TileEntityの内部にあるアイテムをドロップさせる。 TileEntityAluminiumChest tileentity = (TileEntityAluminiumChest) world.getTileEntity(x, y, z); if (tileentity != null) { for (int i = 0; i tileentity.getSizeInventory(); i++) { ItemStack itemStack = tileentity.getStackInSlot(i); if (itemStack != null) { float f = random.nextFloat() * 0.6F + 0.1F; float f1 = random.nextFloat() * 0.6F + 0.1F; float f2 = random.nextFloat() * 0.6F + 0.1F; while (itemStack.stackSize 0) { int j = random.nextInt(21) + 10; if (j itemStack.stackSize) { j = itemStack.stackSize; } itemStack.stackSize -= j; EntityItem entityItem = new EntityItem(world, x + f, y + f1, z + f2, new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage())); if (itemStack.hasTagCompound()) { entityItem.getEntityItem() .setTagCompound(((NBTTagCompound) itemStack.getTagCompound().copy())); } float f3 = 0.025F; entityItem.motionX = (float) random.nextGaussian() * f3; entityItem.motionY = (float) random.nextGaussian() * f3 + 0.1F; entityItem.motionZ = (float) random.nextGaussian() * f3; world.spawnEntityInWorld(entityItem); } } } world.func_147453_f(x, y, z, block); } super.breakBlock(world, x, y, z, block, meta); } } TileEntityAluminiumChest.java package tutorial.aluminiummod; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; public class TileEntityAluminiumChest extends TileEntity implements IInventory { protected ItemStack[] itemStacks = new ItemStack[54]; @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); NBTTagList nbttaglist = new NBTTagList(); for (int i = 0; i itemStacks.length; i++) { if (itemStacks[i] == null) continue; NBTTagCompound nbt1 = new NBTTagCompound(); nbt1.setByte("Slot", (byte) i); itemStacks[i].writeToNBT(nbt1); nbttaglist.appendTag(nbt1); } nbt.setTag("Items", nbttaglist); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); NBTTagList nbttaglist = nbt.getTagList("Items", 10); itemStacks = new ItemStack[54]; for (int i = 0; i nbttaglist.tagCount(); i++) { NBTTagCompound nbt1 = nbttaglist.getCompoundTagAt(i); byte b0 = nbt1.getByte("Slot"); if (0 = b0 b0 itemStacks.length) { itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbt1); } } } @Override public int getSizeInventory() { return 54; } @Override public ItemStack getStackInSlot(int slot) { return itemStacks[slot]; } @Override public ItemStack decrStackSize(int slot, int amount) { if (itemStacks[slot] == null) return null; ItemStack itemstack; if (itemStacks[slot].stackSize = amount) { itemstack = itemStacks[slot]; itemStacks[slot] = null; return itemstack; } itemstack = itemStacks[slot].splitStack(amount); if (itemStacks[slot].stackSize 1) { itemStacks[slot] = null; } return itemstack; } @Override public ItemStack getStackInSlotOnClosing(int slot) { return null; } @Override public void setInventorySlotContents(int slot, ItemStack itemStack) { itemStacks[slot] = itemStack; if (itemStack != null itemStack.stackSize this.getInventoryStackLimit()) { itemStack.stackSize = this.getInventoryStackLimit(); } } @Override public boolean hasCustomInventoryName() { return false; } @Override public String getInventoryName() { return "container.AluminiumMod.AluminiumChest"; } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return worldObj.getTileEntity(xCoord, yCoord, zCoord) != this ? false player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) = 64.0D; } @Override public void openInventory() {} @Override public void closeInventory() {} @Override public boolean isItemValidForSlot(int slot, ItemStack itemStack) { return true; } } AluminiumModGuiHandler.java package tutorial.aluminiummod; import cpw.mods.fml.common.network.IGuiHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class AluminiumModGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntityAluminiumChest) { return new ContainerAluminiumChest(player, (TileEntityAluminiumChest) tileentity); } return null; } @Override public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntityAluminiumChest) { return new GuiAluminiumChest(player, (TileEntityAluminiumChest) tileentity); } return null; } } ContainerAluminiumChest.java package tutorial.aluminiummod; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; public class ContainerAluminiumChest extends Container { private TileEntityAluminiumChest tileEntity; /** アルミニウムチェストのインベントリの第一スロットの番号 */ private static final int index0 = 0; /** プレイヤーのインベントリの第一スロットの番号 */ private static final int index1 = 54; /** クイックスロットの第一スロットの番号 */ private static final int index2 = 81; /** このコンテナの全体のスロット数 */ private static final int index3 = 90; public ContainerAluminiumChest(EntityPlayer player, TileEntityAluminiumChest tileEntity) { // スロットを設定する。 this.tileEntity = tileEntity; for (int iy = 0; iy 6; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(tileEntity, ix + (iy * 9), 8 + (ix * 18), 18 + (iy * 18))); } } for (int iy = 0; iy 3; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix + (iy * 9) + 9, 8 + (ix * 18), 140 + (iy * 18))); } } for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix, 8 + (ix * 18), 198)); } } @Override public boolean canInteractWith(EntityPlayer player) { return tileEntity.isUseableByPlayer(player); } @Override public ItemStack transferStackInSlot(EntityPlayer player, int slotNumber) { ItemStack itemStack = null; Slot slot = (Slot) inventorySlots.get(slotNumber); if (slot != null slot.getHasStack()) { ItemStack itemStack1 = slot.getStack(); itemStack = itemStack1.copy(); if (index0 = slotNumber slotNumber index1) { // アルミニウムチェストのインベントリならプレイヤーのインベントリに移動。 if (!this.mergeItemStack(itemStack1, index1, index3, true)) { return null; } } else { // プレイヤーのインベントリならアルミニウムチェストのインベントリに移動。 if (!this.mergeItemStack(itemStack1, index0, index1, false)) { return null; } } if (itemStack1.stackSize == 0) { slot.putStack((ItemStack) null); } else { slot.onSlotChanged(); } if (itemStack1.stackSize == itemStack.stackSize) { return null; } slot.onPickupFromSlot(player, itemStack1); } return itemStack; } } GuiAluminiumChest.java package tutorial.aluminiummod; import org.lwjgl.opengl.GL11; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; public class GuiAluminiumChest extends GuiContainer { private TileEntityAluminiumChest tileEntity; // GUIのテクスチャの場所を指定する。今回はバニラのラージチェストと同じものを使う。 private static final ResourceLocation GUITEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); public GuiAluminiumChest(EntityPlayer player, TileEntityAluminiumChest tileEnttiy) { super(new ContainerAluminiumChest(player, tileEnttiy)); this.tileEntity = tileEnttiy; ySize = 222; } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { fontRendererObj.drawString(StatCollector.translateToLocal(tileEntity.getInventoryName()), 8, 6, 4210752); fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, 4210752); } @Override protected void drawGuiContainerBackgroundLayer(float tick, int mouseX, int mouseY) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); mc.getTextureManager().bindTexture(GUITEXTURE); int k = (width - xSize) / 2; int l = (height - ySize) / 2; this.drawTexturedModalRect(k, l, 0, 0, xSize, ySize); } } 解説 Instance String modid コアクラスのインスタンスにつけるアノテーション。 登録やインスタンスの生成・代入はForge側がやってくれるので何もしなくてよい。 NetworkRegistry GUIやパケットなどを管理するenum。 void registerGuiHandler(Object mod, IGuiHandler handler) MODのコアクラスのインスタンスと、それに対応したGuiHandlerを登録する処理。 EntityPlayer プレイヤーのEntity継承クラス。 void openGui(Object mod, int modGuiId, World world, int x, int y, int z) 第一引数はコアクラスのインスタンス、第二引数はMOD内でのGUIのID。 プレイヤーにGUIを開かせる。 IGuiHandler GuiHandlerのためのインターフェース。 Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) サーバー側で呼ばれる。 基本的にはIDに対応したContainerを返す。 Worldのインスタンスと座標も引数に含まれているので、TileEntityを取得して判別してもよい。 Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) クライアント側で呼ばれる。 基本的にはIDに対応したGuiを返す。 Container Slot addSlotToContainer(Slot slot) 新たなSlotをコンテナに登録する処理。 boolean canInteractWith(EntityPlayer player) プレイヤーがコンテナを使えるかどうかの判定。 ItemStack transferStackInSlot(EntityPlayer player, int slotNumber) スロットがShift+クリックされた時の処理。 クリックされたスロットの中身を移動する。 boolean mergeItemStack(ItemStack itemStack, int beginIndex, int endIndex, boolean doReverse) 引数のItemStackを指定された範囲内の空のスロットに移動する。 範囲は、beginIndexを含み、endIndexは含まない。 doReverseがtrueの場合は、検索方向がend→beginになる。 GuiContainer コンテナを持つGUIのクラス。 クライアントのみで使用される。 public GuiContainer(Container container) 引数は対応するコンテナ。 void drawGuiContainerForegroundLayer(int mouseX, int mouseY) Guiの前面レイヤーを描画する処理。 文字の描画などをする。 void drawGuiContainerBackgroundLayer(float tick, int mouseX, int mouseY) Guiの背景レイヤーを描画する処理。 Guiのテクスチャの描画などをする。 ResourceLocation リソースの場所を保持するクラス。 public ResourceLocation(String path) コンストラクタ。 引数でリソースの場所を指定する。 "modid textures/..."というように、すべて小文字にしたMODIDと、textures以下のファイルのパスを指定する。 例えば、assets/aluminiummod/textures/gui/gui.pngだとすると、private static final ResourceLocation GUITEXTURE = new ResourceLocation("aluminiummod textures/gui/gui.png");と記述する。 なお、GUIのテクスチャは画像ファイルを正方形にしないと縦横比がおかしくなる可能性があるので、カンバスサイズを256x256や512x512などにしておいて、余白を透明で残しておくと良い。 使用例 オファレンプレゼントボックスを追加している部分。 +オファレンMOD OfalenModCore.java package nahama.ofalenmod; /*略*/ /** * @author Akasata Nahama */ @Mod(modid = OfalenModCore.MODID, name = OfalenModCore.MODNAME, version = OfalenModCore.VERSION) public class OfalenModCore { public static final String MODID = "OfalenMod"; public static final String MODNAME = "Ofalen Mod"; public static final String MCVERSION = "1.7.10"; public static final String OMVERSION = "1.1.0"; public static final String VERSION = "[" + MCVERSION + "]" + OMVERSION; /** coreクラスのインスタンス */ @Instance(MODID) public static OfalenModCore instance; /*略*/ /** 初期化前処理。 */ @EventHandler public void preInit(FMLPreInitializationEvent event) { /*略*/ OfalenModBlockCore.registerBlock(); // 機械類のGUIを登録する。 NetworkRegistry.INSTANCE.registerGuiHandler(this.instance, new OfalenModGuiHandler()); /*略*/ } /*略*/ } OfalenModBlockCore.java package nahama.ofalenmod.core; /*略*/ public class OfalenModBlockCore { /*略*/ public static Block boxPresentOfalen; /** ブロックを登録する処理。 */ public static void registerBlock() { /*略*/ boxPresentOfalen = new BlockPresentBox() .setBlockName("boxPresentOfalen") .setBlockTextureName("ofalenmod present_box"); GameRegistry.registerBlock(boxPresentOfalen, "boxPresentOfalen"); GameRegistry.registerTileEntity(TileEntityPresentBox.class, "TileEntityOfalenPresentBox"); } } BlockPresentBox.java package nahama.ofalenmod.block; import java.util.Random; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import nahama.ofalenmod.OfalenModCore; import nahama.ofalenmod.handler.OfalenModAnniversaryHandler; import nahama.ofalenmod.tileentity.TileEntityPresentBox; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraft.world.World; public class BlockPresentBox extends Block implements ITileEntityProvider { private Random random = new Random(); /** 0 下,1 上,2 横,3 クリスマス下,4;クリスマス上,5 クリスマス横 */ private IIcon[] iicon = new IIcon[6]; public BlockPresentBox() { super(Material.sponge); this.setCreativeTab(OfalenModCore.tabOfalen); this.setHardness(1.0F); this.setResistance(1.0F); this.setStepSound(Block.soundTypeCloth); } @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityPresentBox(); } /** プレイヤーに右クリックされたときの処理。 */ @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { // GUIを開く player.openGui(OfalenModCore.instance, 1, world, x, y, z); return true; } /** ブロックが破壊された時の処理。 */ @Override public void breakBlock(World world, int x, int y, int z, Block block, int meta) { // TileEntityの内部にあるアイテムをドロップさせる。 TileEntityPresentBox tileentity = (TileEntityPresentBox) world.getTileEntity(x, y, z); if (tileentity != null) { for (int i = 0; i tileentity.getSizeInventory(); i++) { ItemStack itemStack = tileentity.getStackInSlot(i); if (itemStack != null) { float f = random.nextFloat() * 0.6F + 0.1F; float f1 = random.nextFloat() * 0.6F + 0.1F; float f2 = random.nextFloat() * 0.6F + 0.1F; while (itemStack.stackSize 0) { int j = random.nextInt(21) + 10; if (j itemStack.stackSize) { j = itemStack.stackSize; } itemStack.stackSize -= j; EntityItem entityItem = new EntityItem(world, x + f, y + f1, z + f2, new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage())); if (itemStack.hasTagCompound()) { entityItem.getEntityItem().setTagCompound(((NBTTagCompound) itemStack.getTagCompound().copy())); } float f3 = 0.025F; entityItem.motionX = (float) random.nextGaussian() * f3; entityItem.motionY = (float) random.nextGaussian() * f3 + 0.1F; entityItem.motionZ = (float) random.nextGaussian() * f3; world.spawnEntityInWorld(entityItem); } } } world.func_147453_f(x, y, z, block); } super.breakBlock(world, x, y, z, block, meta); } /** ブロックのアイコンを登録する処理。 */ @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister register) { for (int i = 0; i 6; i++) { iicon[i] = register.registerIcon(this.getTextureName() + "-" + i); } } /** ブロックのアイコンを返す。 */ @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int meta) { int i = 2; if (side == 0) i = 0; if (side == 1) i = 1; if (OfalenModAnniversaryHandler.isChristmas) i += 3; return iicon[i]; } } TileEntityPresentBox.java package nahama.ofalenmod.tileentity; import nahama.ofalenmod.handler.OfalenModAnniversaryHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; public class TileEntityPresentBox extends TileEntity implements IInventory { protected ItemStack[] itemStacks = new ItemStack[54]; protected String owner; /** プレイヤーがインベントリを開けた時の処理。 */ public void openInventory(EntityPlayer player) { if (owner != null || worldObj.isRemote) return; // オーナーに設定し、中身を上書きする。 owner = player.getCommandSenderName(); ItemStack[] presents = OfalenModAnniversaryHandler.getPresents(player); if (presents == null) return; itemStacks = presents; } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); NBTTagList nbttaglist = new NBTTagList(); for (int i = 0; i itemStacks.length; i++) { if (itemStacks[i] == null) continue; NBTTagCompound nbt1 = new NBTTagCompound(); nbt1.setByte("Slot", (byte) i); itemStacks[i].writeToNBT(nbt1); nbttaglist.appendTag(nbt1); } nbt.setTag("Items", nbttaglist); nbt.setString("Owner", owner); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); NBTTagList nbttaglist = nbt.getTagList("Items", 10); itemStacks = new ItemStack[54]; for (int i = 0; i nbttaglist.tagCount(); i++) { NBTTagCompound nbt1 = nbttaglist.getCompoundTagAt(i); byte b0 = nbt1.getByte("Slot"); if (0 = b0 b0 itemStacks.length) { itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbt1); } } owner = nbt.getString("Owner"); } /** インベントリのスロット数を返す。 */ @Override public int getSizeInventory() { return 54; } /** スロットのアイテムを返す。 */ @Override public ItemStack getStackInSlot(int slot) { return itemStacks[slot]; } /** スロットのスタック数を減らす。 */ @Override public ItemStack decrStackSize(int slot, int amount) { if (itemStacks[slot] == null) return null; ItemStack itemstack; if (itemStacks[slot].stackSize = amount) { itemstack = itemStacks[slot]; itemStacks[slot] = null; return itemstack; } itemstack = itemStacks[slot].splitStack(amount); if (itemStacks[slot].stackSize 1) { itemStacks[slot] = null; } return itemstack; } @Override public ItemStack getStackInSlotOnClosing(int slot) { return null; } /** スロットの中身を設定する。 */ @Override public void setInventorySlotContents(int slot, ItemStack itemStack) { itemStacks[slot] = itemStack; if (itemStack != null itemStack.stackSize this.getInventoryStackLimit()) { itemStack.stackSize = this.getInventoryStackLimit(); } } /** 金床で設定された名前を持つかどうか。 */ @Override public boolean hasCustomInventoryName() { return false; } /** インベントリの名前を返す。 */ @Override public String getInventoryName() { return "container.OfalenMod.PresentBox"; } /** このインベントリの最大スタック数を返す。 */ @Override public int getInventoryStackLimit() { return 64; } /** プレイヤーが使用できるかどうか。 */ @Override public boolean isUseableByPlayer(EntityPlayer player) { if (owner != null !player.getCommandSenderName().equals(owner)) return false; return worldObj.getTileEntity(xCoord, yCoord, zCoord) != this ? false player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) = 64.0D; } @Override public void openInventory() {} @Override public void closeInventory() {} /** スロットにアクセスできるかどうか。 */ @Override public boolean isItemValidForSlot(int slot, ItemStack itemStack) { return false; } } OfalenModGuiHandler.java package nahama.ofalenmod.handler; /*略*/ public class OfalenModGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (id == 2) return new ContainerItemShield(player); if (id == 3) return new ContainerItemTeleporter(player); if (id == 4) return new ContainerItemFloater(player); if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntitySmeltingMachine) { return new ContainerSmeltingMachine(player, (TileEntitySmeltingMachine) tileentity); } if (tileentity instanceof TileEntityRepairMachine) { return new ContainerRepairMachine(player, (TileEntityRepairMachine) tileentity); } if (tileentity instanceof TileEntityConversionMachine) { return new ContainerConversionMachine(player, (TileEntityConversionMachine) tileentity); } if (tileentity instanceof TileEntityTeleportMarker) { return new ContainerTeleportMarker(player, (TileEntityTeleportMarker) tileentity); } if (tileentity instanceof TileEntityPresentBox) { return new ContainerPresentBox(player, (TileEntityPresentBox) tileentity); } return null; } @Override public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (id == 2) return new GuiItemShield(player); if (id == 3) return new GuiItemTeleporter(player); if (id == 4) return new GuiItemFloater(player); if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntitySmeltingMachine) { return new GuiSmeltingMachine(player, (TileEntitySmeltingMachine) tileentity); } if (tileentity instanceof TileEntityRepairMachine) { return new GuiRepairMachine(player, (TileEntityRepairMachine) tileentity); } if (tileentity instanceof TileEntityConversionMachine) { return new GuiConversionMachine(player, (TileEntityConversionMachine) tileentity); } if (tileentity instanceof TileEntityTeleportMarker) { return new GuiTeleportMarker(player, (TileEntityTeleportMarker) tileentity); } if (tileentity instanceof TileEntityPresentBox) { return new GuiPresentBox(player, (TileEntityPresentBox) tileentity); } return null; } } ContainerPresentBox.java package nahama.ofalenmod.inventory; import nahama.ofalenmod.tileentity.TileEntityPresentBox; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; public class ContainerPresentBox extends Container { private TileEntityPresentBox tileEntity; /** プレゼントボックスのインベントリの第一スロットの番号 */ private static final int index0 = 0; /** プレイヤーのインベントリの第一スロットの番号 */ private static final int index1 = 54; /** クイックスロットの第一スロットの番号 */ private static final int index2 = 81; /** このコンテナの全体のスロット数 */ private static final int index3 = 90; public ContainerPresentBox(EntityPlayer player, TileEntityPresentBox tileEntity) { this.tileEntity = tileEntity; tileEntity.openInventory(player); for (int iy = 0; iy 6; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(tileEntity, ix + (iy * 9), 8 + (ix * 18), 18 + (iy * 18))); } } for (int iy = 0; iy 3; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix + (iy * 9) + 9, 8 + (ix * 18), 140 + (iy * 18))); } } for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix, 8 + (ix * 18), 198)); } } @Override public boolean canInteractWith(EntityPlayer player) { return tileEntity.isUseableByPlayer(player); } @Override public ItemStack transferStackInSlot(EntityPlayer player, int slotNumber) { ItemStack itemStack = null; Slot slot = (Slot) inventorySlots.get(slotNumber); if (slot != null slot.getHasStack()) { ItemStack itemStack1 = slot.getStack(); itemStack = itemStack1.copy(); if (index0 = slotNumber slotNumber index1) { // プレゼントボックスのインベントリならプレイヤーのインベントリに移動。 if (!this.mergeItemStack(itemStack1, index1, index3, true)) { return null; } } else { if (index1 = slotNumber slotNumber index2) { // プレイヤーのインベントリならクイックスロットに移動。 if (!this.mergeItemStack(itemStack1, index2, index3, false)) { return null; } } else if (index2 = slotNumber slotNumber index3 !this.mergeItemStack(itemStack1, index1, index2, false)) { // クイックスロットからプレイヤーのインベントリに移動できなかったら終了。 return null; } } if (itemStack1.stackSize == 0) { slot.putStack((ItemStack) null); } else { slot.onSlotChanged(); } if (itemStack1.stackSize == itemStack.stackSize) { return null; } slot.onPickupFromSlot(player, itemStack1); } return itemStack; } } GuiPresentBox.java package nahama.ofalenmod.gui; import org.lwjgl.opengl.GL11; import nahama.ofalenmod.inventory.ContainerPresentBox; import nahama.ofalenmod.tileentity.TileEntityPresentBox; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; public class GuiPresentBox extends GuiContainer { private TileEntityPresentBox tileEntity; private static final ResourceLocation GUITEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); public GuiPresentBox(EntityPlayer player, TileEntityPresentBox tileEnttiy) { super(new ContainerPresentBox(player, tileEnttiy)); this.tileEntity = tileEnttiy; ySize = 222; } @Override protected void drawGuiContainerForegroundLayer(int par1, int par2) { fontRendererObj.drawString(StatCollector.translateToLocal(tileEntity.getInventoryName()), 8, 6, 4210752); fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, 4210752); } @Override protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); mc.getTextureManager().bindTexture(GUITEXTURE); int k = (width - xSize) / 2; int l = (height - ySize) / 2; this.drawTexturedModalRect(k, l, 0, 0, xSize, ySize); } } コメント この項目に関する質問などをどうぞ。 GUIのテクスチャをオリジナルのものにする場合どう記述すれば、よいのでしょうか? - 新人もっだー 2015-12-20 12 20 13 解説/public ResourceLocation(String path)に追記しましたのでご確認ください。自分で指定したパスにバニラのラージチェストのテクスチャを改変したものを保存すればできます。 - Tom Kate 2015-12-21 16 52 24 コピペでもコンストラクター ContainerAluminiumChest(EntityPlayer, TileEntityChest) は未定義ですとなります。 - 新人もっだー 2015-12-26 11 26 55 それは、Eclipse上でコンパイルエラーの検出がされたということでしょうか?どの行でのエラーかを教えていただけないでしょうか。 - 赤砂蛇凪浜 2015-12-26 13 48 01 ContainerAluminiumChestのreturn new ContainerChest(player, (TileEntityChest) tileentity);no - 新人もっだー 2015-12-28 08 51 55 の行です - 新人もっだー 2015-12-28 08 52 37 このチュートリアルの中に該当する行がありません。一度コピー ペーストしなおしてみてください。 - 赤砂蛇凪浜 2015-12-28 09 36 26 import cpw.mods.fml.common.Mod.Instance;が書き込んでから保存するとなぜかそれだけ消えてしまうのですが、なんで何でしょうか? - san 2016-09-11 08 20 49 IDE(Eclipse)のimport文自動編集が消しているのだと思われます。@Instanceの部分にエラーが出ていなければ特に問題はないと思います。 - 赤砂蛇凪浜 2016-09-16 07 35 27 醸造台やエンチャント台、装備スロットのように、スロット内に一部のアイテムのみ入れられるようにするにはどうすれば良いのでしょうか? - 名無しさん 2016-12-02 01 33 32 addSlotToContainerでSlotを継承した自作のクラスを渡せばよいです。その際、isItemValidをオーバーライドすれば入れられるアイテムを、canTakeStackをオーバーライドすれば取り出せるアイテムを制御できます。分かりにくかったらすみません。後ほど本文への掲載も検討します。 - 赤砂蛇凪浜 2016-12-04 10 50 12 GUIに文字を入れて翻訳するのはどうやるんですか - HIROMARU (2021-01-09 11 38 30) 名前
https://w.atwiki.jp/kns-wiki/pages/320.html
NW-Spriggan Light Combat Shotgun詳細 #ref error :画像URLまたは、画像ファイル名を指定してください。 使用可能パーク #ref error :画像URLまたは、画像ファイル名を指定してください。 アンロックレベル Lv.-- 価格 £ 特徴 [部分編集] Power 1 Head-Shot Power 1 Radius 0 Penetration 0 Pellet 45 Recoil 77 Spread 41 Fire-Speed 6 Reload-Speed 75 Effective-Range 2 Magazine Capacity 2 Carry Ammunition 4 Heal-Power 0 Weight 2 名前 コメント
https://w.atwiki.jp/skyrim_mod/pages/23.html
スクリプトmod製作過程 スクリプトを使ったmodの製作過程を一から纏めてみました。 トライ&エラーで修正しつつmodの作成を目指します。 言語としてのpapyrusの説明は最小限に留めています。 ifとwhileしかない言語なのでそれ自体はそんなに難しくはないですので。 どんなmodを作るか考える。 仕組みを考える CKの作業1Skyrim.esmの読み込み オブジェクト(Object) スクリプト(Script)1繰り返し処理をする 攻撃対象の取得 Onhitを使う1 イベント(Event) 再検討 スペル(Spell) CKの作業2マジックエフェクト(Magic Effect)の作成 既存のエフェクトを複製 既存のスペルを複製 現状確認 スクリプト(Script)2スペルをプレゼントする プロパティ(Property) aaaBundoriTargetスクリプト完成 スクリプト(Script)3イベント ぶんどり発動条件 定義 アイテムの選定 ぶんどる 完成?! 不満点服を着てしまうぞ!フザケンな。 ぶんどり100%ないわー もうちょっと演出をなんとかしてくれ 不意打ちでぶんどる出来ない 更新はないの? どんなmodを作るか考える。 おぼろげに"こんなモノ"が欲しいと考えるのは簡単なのですが、その"こんなモノ"を形にするのはとても大変です。 今回は、かの有名な国産RPGの一つのアビリティからアイデアを頂戴して"ぶんどる"を作ることにします。 実際にskyrimで作れるのかどうかが心配です… 仕組みを考える ここにある関数を使って作っていきますが、ある意味で一番大変であり重要な所です。 "こんなモノ"をどのようにすればskyrimのmodとして形にできるのでしょう? とりあえず"ぶんどる"を作るには、どのような処理をするのかを考えます。 プレイヤーの「攻撃対象を取得」して「攻撃を当てた時」に、対象の「手持ちアイテム」を「盗む」 なんとなくコレで出来そうです。 では、上記のURLでそれっぽい物を探します。 ※適当に検索等で探しています 攻撃対象を取得 → GetCombatTarget 攻撃を当てた時 → OnHit 手持ちアイテム → GetNumItems 盗む → RemoveItem 探した結果、出来そうな物が揃っていましたので難しいことをしないでも可能なようです。 早速、作り始めることにします。 今回のようにスクリプトで何が出来て何が出来ないのかを 事前に判断できれば良いのですが、始めての人には難しいと思います。 作りたいものが出来たら兎に角作ってみましょう。 CKの作業1 Skyrim.esmの読み込み まずはCKを起動します。 CKウィンドウの左上にあるFile→Dataと選んだあとskyrim.esmをダブルクリックしてチェックを入れてOKボタンを押します。 エラー表示は[キャンセル]を押してください。 これでskyrimの世界を読み込んだ状態になりました。 これから変更を加えた場合、skyrimの"何か"を変更することになりますが マスターファイル(esm)自体は追加・編集をする事が出来ませんので安心してください。 保存をする場合は"何か"の部分を上書きするプラグイン(esp)を作ることになります。 オブジェクト(Object) 攻撃対象を取得するのにGetCombatTargetを使うことにしていますが スクリプトは何らかのオブジェクトにくっつけて動作する必要があります。 例えば、ゲーム開始時に自動で"Hello World"と文字を出そうとした場合は 「スクリプトをquestに付けて、そのquestをスタートさせた時に文字を出す」 「プレイヤーにスクリプトを付けて、ゲームに読み込まれた時に文字を出す」 といった形になります。本であれ魔法であれクエストであれ とにかく何かに付ける事で動かす事が出来ると覚えてください。 今回はプレイヤーの攻撃対象を取得するのですから"Player"に付ける事にします。 { ※この説明ではスクリプトを直接Playerに付けていますが、この方法は現在はほぼ使われていません。 新規QuestのReferenceAliasでPlayerを指定。スクリプトをAliasに張り付ける手法が一般的です。 } 画面左にある"object window"の上のあるFilterに"player"と入れて マウスでActorを選択すれば"Player"を発見できるはずです。 ダブルクリップで開き、Actor window左側にあるScriptsの"Add"を押します。 出てきたscript windowの上段の"[New File]"を押せば 新しいスクリプトをくっ付ける事が出来ます。 スクリプトの名前を決めるwindowが出てきました。 今回は"aaaBundoriTarget"とでもしておきます。 他はとりあえずそのままでおkです。 aaa等を付けることでfilterが使いやすくなります。 スクリプトはオブジェクトに付いたので一度保存しておきます。 Actor windowの左下の[OK]を押して、閉じてください。 保存をするためには、開いたwindowは閉じて置かなければいけません。 CKのメニューバーFile→Saveと選んで"BundoriTutorial"と名前を入力しました。 先ほど閉じた"Player"を再度開きます。 "aaaBundoriTarget"がScriptとして追加されていますが、"aaaBundoriTarget"の所で右クリックするとメニューが出てくるので、"Edit Source"を選びます。 ※その下の"Open in External Editor"を選ぶとpscファイルに関連付けされたテキストエディタで編集することができます。 スクリプト(Script)1 今回、私が考えているスクリプトはこのような感じです。 1 繰り返し処理をする 2 プレイヤーの攻撃対象を取得する 3 攻撃対象に攻撃を与えたか確認する 4 確認できたら何を持っているか確認する 5 ランダムで選んだアイテムをプレイヤーに移動する 6 1にもどる では順番にやっていきましょう。 繰り返し処理をする 繰り返し処理に関してはこのwikiの逆引きリファレンスの中にある常時稼動させるスクリプトを参考にします。 実際の処理の部分を置き換えればそのまま使えそうです。 攻撃対象の取得 ck wikiのGetCombatTargetのページを開きます。 細かい仕様は後に回しましょう。用があるのはExamplesです。 素晴らしいことに必要であるプレイヤーの攻撃対象を取得するサンプルがありました。 これをそのまま使います。 先ほどの繰り返し処理と併せてこのような感じになっています。 ここで一度スクリプトを保存します。Edit windowのFile→Save(ctrl+S)です。 これで攻撃対象の取得を一秒ごとに繰り返すはず… ところが…なにやらエラーらしきものが出てしまいました。 [いいえ]を押して修正をします。 下段に理由がかいてありますが、8行目のTargetRefが指定されていないのが問題のようです。 c \...\aaaBundoriTarget.psc(8,1) variable TargetRef is undefined c \...\aaaBundoriTarget.psc(8,1) type mismatch while assigning to a none (cast missing or types unrelated) 8行目という事はGetCombatTargetの部分なのでGetCombatTargetのページに戻ります。。 答えはSyntaxにありました。 赤丸がついた所、Functionの前にActorと書いてあります。 これはGetCombatTargetがActor型で返すと言うことなので、8行目のTargetRefはActor型でなければいけません。 TargetRefの頭にActorと付けて指定することで無事に成功しました。 Onhitを使う1 先ほどと同じようにOnHitのページを開きます。 とりあえずはExamplesからなのですが…先ほどとは少し違います。 どうやら、OnHitはFunctionではなく"Event"のようです… イベント(Event) "Event"はスクリプトを動かす為のトリガーです。 本を読むとOnReadが、扉を開くとOnOpenのイベントが起こります。 ですが重要な事は、その動作を受け取ったオブジェクトに対してイベントが起こる事です。 上記の例の場合、OnReadのイベントが起こるのは本のオブジェクトであり、本を読んだ人には起こりません。 極稀な一部のイベントを除いて、ほぼ全てのイベントは受動の為、慣れるまではイライラすると思います。 今回の場合、OnHitは攻撃対象(TargetRef)に起こり、Playerには起こりません。 再検討 当初の予定のままでは駄目なようなので予定を変更することにしました。 現在作った部分はそのままに再検討しています。 その時に書いたメモはこんな感じです 手書きのものを画像で作りなおしてはいますが、だいたいこのような感じです。 修正案では先ほどの物とは別のスクリプトを用意しようとしています。 攻撃対象は特定されていない今回の場合はどのようにすれば良いのでしょう? 今回は攻撃対象にスクリプトを動的にくっつける為に"Spell"を使う事にします。 スペル(Spell) スペルは様々な"Magic Effect"を組み合わせたもので、アビリティ・病気・パワー・呪文・スクロール・シャウト等全てスペルの一つです。 明かりの魔法のように "Spell - MagicEffect" が一対になっているものもあれば、術者のレベルで使用するMagicEffectを変えるもの、雷の魔法のようにダメージ+麻痺にする物もあります。 とりあえず、スペルにはMagic Effectが必要だと覚えてください。 SpellやMagic Effectの細かい部分はCK wikiのここが一番詳しいです。 CKの作業2 マジックエフェクト(Magic Effect)の作成 まずはぶんどりスペルのマジックエフェクト部分から作ります。 最初のうちは新規に作るよりも間違いが少なく良いと思います 既存のエフェクトを複製 複製と言っても適当な物を選んでしまっていいのでしょうか? 今回は"abGhost"を事前に選んでおきました。 理由として アビリティである。 ビジュアルエフェクトがついている。 このエフェクトを単独で使っているスペルがある。 があります。 フィルターに "abg" と入力すれば"abGhost"が見つかるので開いてください。 開いたら左上にあるIDとNameをそれぞれ"aaaBundoriOnhit","Bundori Onhit"に変更します。 次に画面左側のFlagsの中の"No Hit Effect"にチェックを入れてください。 これにチェックを入れるとvisual effectを無視します。 逆に効果が出ているか確認したい時はチェックを外します。 また、右下の"Papyrus Scrips"にある"magicsetActorAlphaScript"は不要なので削除しておきました。 選択して右側のRemoveボタンを押してください。 代わりに2個目の自作スクリプト"aaaBundoriOnHit"を新規作成して付けておきます。 とりあえず今は付けておくだけです。 最後に下の方にある[OK]を押します。 勝手にIDを変更した為に確認のダイアログが出てきますが、既存エフェクトを元にして新規作成したいので[OK]を押します。 これで"abGhost"を元にしたマジックエフェクト"aaaBundoriOnhit"を作りました。 既存のスペルを複製 次はスペルなのですが既存スペルに"abGhostを使っている物があります。 せっかくなのでそちらのスペルも使わせていただきました。 abGhostを右クリックして一番下 "Use Info" を開きます。 このリポートは今後よく使う事になると思います。とても便利。 ※ここから使用されている物・所が一覧で参照できる このリポートからも直接スペルを開く事が出来ます。 前回と同じようにID,Nameを変えた後、今回は右側のエフェクト"Ghost Visuals"も変更しておきます。 右クリックしてEditを選んでください。ダブルクリックでも良いです。 "Ghost Visuals"は"abGhost"の事なので、今回作った"Bundori Onhit"に変更しておきます。 ID順に並んでいるのでaaaを付けている事で一番上にありました。 後はそのまま変更しないで問題ありません。 現状確認 予定通りにスペルをつくりました。 これで後はスクリプトの完成を目指すだけになりました。 Category ID Script Actor Player aaaBundoriTarget Magic Effect aaaBundoriOnhit aaaBundoriOnhit Spell aaaBundoriAbility ところで別々のオブジェクトにスクリプトが付いた事でCKでの作業がしづらくなりました。 毎回、フィルターを切り替えても良いのですがもっと簡単に出来る方法があります。 object windowの右側、一覧部分の適当な部分で右クリックをして出てくるメニューから"Create New Object Window"を選ぶと 新しいObject windowが出てきます。 これを使えばPlayerとaaaの2つのフィルターを同時に使う事が出来るので非常に便利です。 ※こんな感じで同時に出しておくことが出来る スクリプト(Script)2 スペルをプレゼントする 現状確認の項で見た通りPlayerについている"aaaBundoriTarget"は現状対象の取得だけ行なっています。 これに先ほど作ったスペルをプレゼントする部分を追加します。 GetCombatTargetの行の後に次のように加えました。 Actor TargetRef = Game.GetPlayer().GetCombatTarget() if TargetRef != none TargetRef.AddSpell(aaaBundoriAbility) endif TargetRefが空じゃない場合、先ほど作った"aaaBundoriAbility"をTargetRefに与えると言うもの。 ですが、これを保存しようとするとやっぱりエラーが出ました。 aaaBundoriAbilityの未定義エラー…スクリプトにはCKにあるIDを直接書いても駄目なようです。 存在するスペルをスクリプト内で使う為には"Property"を使って指定してあげる必要があります。 今回は[はい]を選び、スクリプトはその状態のまま保存して"Property"の定義を行います。 プロパティ(Property) プロパティは外部(主にCK)からオブジェクトや変数を指定したい場合に使います。 面倒くさいように感じますがプロパティがある事で汎用性のあるスクリプト作成が可能になります。 "Player"のScriptsから"Properties"を選びます。 Add Propartyを選び、更にtypeを指定(今回はSpell)。 今回は汎用スクリプトではありませんので"aaaBundoriAbility"としておきます。 IDと同じにすると自動的で割り当ててくれますが、ちゃんと指定されていることも確認します。 これで"aaaBundoriAbility"の定義が出来ました。 もう一度"Edit Source"を開き保存をしてください。 今度はエラーも無く成功しました。 aaaBundoriTargetスクリプト完成 一つ目のスクリプトが完成しました。 この状態でCKの保存をしましょう。 Scriptname aaaBundoriTarget extends ObjectReference Event Oninit() RegisterForSingleUpdate(1) EndEvent Event OnUpdate() Actor TargetRef = Game.GetPlayer().GetCombatTarget() if TargetRef != none TargetRef.AddSpell(aaaBundoriAbility) endif RegisterForSingleUpdate(1) EndEvent SPELL Property aaaBundoriAbility Auto スクリプト(Script)3 最後にもう一つのスクリプトを作りました。 こちらのスクリプトに関しては作成済みのものを使い、簡単にを説明していきます。 Scriptname aaaBundoriOnhit extends ActiveMagicEffect Event OnHit(ObjectReference akAggressor,Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) if akAggressor != Game.Getplayer() return elseif akSource as Spell return elseif akProjectile != none return endif Actor targetRef = GetTargetActor() int index = targetRef.GetNumItems() form akForm if index 1 int random = Utility.RandomInt(1, index) akForm = targetRef.GetNthForm(random) elseif index == 1 akForm = targetRef.GetNthForm(index) endif if akForm != none targetRef.RemoveItem(akForm,1,false,Game.GetPlayer()) endif EndEvent イベント Event OnHit(ObjectReference akAggressor,Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) ぶんどり発動条件 if akAggressor != Game.Getplayer() return elseif akSource as Spell return elseif akProjectile != none return endif 違った場合Returnを返して処理を終了させています。 上から順に プレイヤーの攻撃ではない場合 魔法で攻撃をしている場合 飛び道具で攻撃している場合 となります。 現在はプレイヤーの攻撃にしか反応しないようになっています。 modを拡張しようとした場合、条件の緩和や追加なども考えられます。 定義 Actor targetRef = GetTargetActor() int index = targetRef.GetNumItems() form akForm このイベント内で使用する変数を用意しています。 一行目、GetTargetActor()は本来 "MagicEffectProperty.GetTargetActor()"と言うようにしなければいけませんが、省略した場合予約語selfが指定されたことになります。 この場合のSelfはMagic Effectの"aaaBundoriOhHit"を指していますが、この事はスクリプトの一行目にあるScriptnameのextendsで何を拡張するスクリプトなのか宣言されています。 Scriptname aaaBundoriOnhit extends ActiveMagicEffect もちろん self.GetTargetActor()と言うようにしても構いません。 二行目、GetNumItems()はSKSEを使った拡張関数でコンテナ(宝箱)のアイテム種類の数を返します。 その為、ぶんどりmodはSKSEが必須となっています。 アイテムの選定 if index 1 int random = Utility.RandomInt(1, index) akForm = targetRef.GetNthForm(random) elseif index == 1 akForm = targetRef.GetNthForm(index) endif アイテムの種類数が二個以上あればランダムで、一個ならそれをakFormにしています。 現在akFormは全てのアイテムの内の何かと同じオブジェクトを指していることになります。 同じものですがそのもの自体ではありません。 ぶんどる if akForm != none targetRef.RemoveItem(akForm,1,false,Game.GetPlayer()) endif 最後にプレイヤーに向けてアイテムを移動します。 完成?! ついに完成?!しました。早速動かしてみましょう。 なんだかアレなmodが出来た気もします。しかし夢が広がりそうでもあります。 とりあえずは脱が…ぶんどる事が出来ましたので良しとしましょう。 出来た物はここを置いておきます。 不満点 ここからはこのmodの問題点・不満な所をあげて、改善案が思いつくのなら考えていきたいと思います。 服を着てしまうぞ!フザケンな。 modとしての動作は問題ないのですがスカイリムの仕様のために、完全に装備を外してしまうと何処からか鎧・服を持ちだしてきて着てしまいます。 靴は対象外にする等の処理を加えるか、鎧を取った後にぶんどれない透明な服を着せるとか少し考えなければいけません。 でもやっぱ足元だけ残ってるのがロマンだと思う。 ぶんどり100%ないわー 現在は攻撃が当たったらすぐにアイテムを剥ぎに行っていますがFFの「ぶんどる」はランダムです。 元々の確率を低くして、敵の体力に比例して確率が上がっていくような処理を加えても良いかも知れません。 もうちょっと演出をなんとかしてくれ いきなり取ってしまうのでもう少しなにかあっても良いですね。 ぶんどったものはその場に散乱するとかあっても良いのかな? …今考えたら過剰演出かも知れません。 不意打ちでぶんどる出来ない 対象のreferece取得が簡単で分かりやすいのでGetTargetActorを使いましたが、本当はスペルをプレゼントする相手は攻撃対象じゃなくても構わないです。 攻撃前にスペルをプレゼントする仕組みを考えれば可能です。 少し冗長になるので今回は簡単な方を選びました。 更新はないの? ありません。権利等全てフリーなmodです。 更新したいと思った人が引き継いで結構です。 出来たら更新した部分と手法をwikiに反映して欲しいです
https://w.atwiki.jp/battlefield1918/pages/257.html
PATERNKOFEL -モンテ・パテルノ- 目次 ブリーフィング 全体マップ チケット設定 陣地 登場兵器 解説 史実 コメント ブリーフィング Located directly at the Toblinger Knoten, the central point of the austrian Drei-Zinnen-front, stands the Paternkofel, a 2,744 meter high mountain. Because the military action is lasting since 1915, the italian general Segator decided to expand the mountain-fortifications to a strong fortress. A result of the long battle at the Paternkofel is the ruin of the near Drei-Zinnen-Hut, which was destroyed from italian artillery in May 1915. That happened two months before the builder of the hut himself died during a sole attack at the Paternkofel s peak. トブリンガー・クノーテンに位置し、オーストリアのドライ・チンネン(トレ・チーメ・ディ・ラヴァレド)戦線の中心地であるモンテ・パテルノは2,744mの高さを持つ。ここでの戦闘は1915年以来続いているため、イタリア軍のセガート将軍は強力な要塞を拡張することにした。長期戦となったモンテ・パテルノの戦闘において、1915年5月にはドライ・チンネンの軍事建物がイタリア軍の砲撃で破壊された。それはモンテ・パテルノにおける攻撃がピークに達し、その建設部隊が戦死する2ヶ月前のことであった。 全体マップ チケット設定 陣営 比率(COOP) 減少速度(COOP) 100% (-%) 10 (-) 110% (-%) 10 (-) 陣地 コンクエストモード 陣地名 初期陣営 価値 白旗時間 確保時間 補足 Drei_Zinnen_Huette 40 - - イタリア軍確保不可。 Paternsattel 40 - - オーストリア=ハンガリー軍確保不可。 Southeast_Paternkofel 20 14 14 South_Paternkofel 10 14 14 Peak_Paternkofel 20 10 10 North_Paternkofel 20 10 10 East_Paternkofel 10 14 14 登場兵器 コンクエストモード 固定兵器 Mod.1906 27口径75mmカノン砲Mle1913 105mmカノン砲TR3インチ ストークス迫撃砲9.45インチ重塹壕迫撃砲 フライング・ピッグビラール・ペロサ Mod.1915砲隊鏡 シュコダ M15 75mm山砲13口径149mm榴弾砲ライヒター・ミーネンヴェルファー・システム "ランツ" 9.15cm軽塹壕迫撃砲シュヴァルツローゼ M.07/12砲隊鏡 ピックアップキット 自動小銃兵キット衛生兵キット 短機関銃兵キット衛生兵キット 解説 未編集 史実 未編集 コメント コメントは最新20件が表示されます。 (過去のコメントを参照) 名前 コメント すべてのコメントを見る